package com.share.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.share.common.core.exception.ServiceException;
import com.share.common.security.utils.SecurityUtils;
import com.share.device.domain.Cabinet;
import com.share.device.domain.CabinetSlot;
import com.share.device.domain.CabinetType;
import com.share.device.domain.PowerBank;
import com.share.device.mapper.CabinetMapper;
import com.share.device.mapper.CabinetSlotMapper;
import com.share.device.mapper.CabinetTypeMapper;
import com.share.device.service.ICabinetService;
import com.share.device.service.IPowerBankService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zxl
 * @date 2025年03月20日 16:54
 */
@Service
public class CabinetServiceImpl extends ServiceImpl<CabinetMapper, Cabinet> implements ICabinetService {

    //CabinetMapper不用手动注入，因为在ServiceImpl中已经注入了，只不过名字叫baseMapper

    @Resource
    CabinetTypeMapper cabinetTypeMapper;

    @Resource
    CabinetSlotMapper cabinetSlotMapper;

    @Resource
    IPowerBankService powerBankService;
    @Override
    public List<Cabinet> selectCabinetList(Cabinet cabinet)
    {
        return baseMapper.selectCabinetList(cabinet);
    }

    /**
     * 保存柜机信息
     * @param cabinet
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int saveCabinet(Cabinet cabinet) {
        //1.先判断柜机编号是否已经存在，如果已经存在，则抛出异常
        long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
        if (count > 0) {
            throw new ServiceException("该柜机编号已存在");
        }
        //2.根据柜机类型id查询柜机类型（获取总插槽数量和可用插槽数量）
        CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());
        // 设置总插槽数量和可用插槽数量
        cabinet.setTotalSlots(cabinetType.getTotalSlots());
        cabinet.setFreeSlots(cabinetType.getTotalSlots());
        cabinet.setUsedSlots(0);
        // 可用充电宝数量默认为0，因为刚加的柜机，还没有放充电宝
        cabinet.setAvailableNum(0);
        cabinet.setCreateTime(new Date());
        cabinet.setCreateBy(SecurityUtils.getUsername());
        // 保存柜机信息
        this.save(cabinet);

        int size = cabinetType.getTotalSlots();
        // 处理柜机插槽信息
        for (int i = 0; i < size; i++) {
            CabinetSlot cabinetSlot = new CabinetSlot();
            //柜机id
            cabinetSlot.setCabinetId(cabinet.getId());
            // 插槽编号
            cabinetSlot.setSlotNo(i + 1 + "");
            // 创建时间，创建人
            cabinetSlot.setCreateTime(new Date());
            cabinetSlot.setCreateBy(SecurityUtils.getUsername());
            cabinetSlotMapper.insert(cabinetSlot);
        }
        return 1;
    }

    /**
     * 修改柜机信息
     * @param cabinet
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updateCabinet(Cabinet cabinet) {
        //获取旧的数据，只有status为0未投入的柜机才可以修改
        Cabinet oldCabinet = this.getById(cabinet.getId());

        if (null == oldCabinet) {
            throw new ServiceException("该柜机不存在");
        }
        // 能走到这，说明oldCabinet不为空,所以这个if不能加非空判断
        if (!"0".equals(oldCabinet.getStatus())) {
            throw new ServiceException("该柜机已投放，无法修改");
        }
        //判断柜机编号是否改变
        if (!oldCabinet.getCabinetNo().equals(cabinet.getCabinetNo())) {
            //不一样，说明修改柜机编号了，要判断新的柜机编号是否已经存在
            long count = this.count(new LambdaQueryWrapper<Cabinet>().eq(Cabinet::getCabinetNo, cabinet.getCabinetNo()));
            if (count > 0) {
                throw new ServiceException("该柜机编号已存在");
            }
        }
        //判断是否修改了柜机类型
        if (oldCabinet.getCabinetTypeId().equals(cabinet.getCabinetTypeId())) {
            //修改了柜机类型，要重新计算柜机插槽数目和可用插槽数量
            CabinetType cabinetType = cabinetTypeMapper.selectById(cabinet.getCabinetTypeId());
            // 设置总插槽数量和可用插槽数量
            cabinet.setTotalSlots(cabinetType.getTotalSlots());
            cabinet.setFreeSlots(cabinetType.getTotalSlots());
            cabinet.setUsedSlots(0);
            cabinet.setAvailableNum(0);
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            //更新柜机信息
            this.updateById(cabinet);
            // 删除所有插槽，重新添加插槽
            cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
            Integer size = cabinetType.getTotalSlots();
            for (Integer i = 0; i < size; i++) {
                CabinetSlot cabinetSlot = new CabinetSlot();
                cabinetSlot.setCabinetId(cabinet.getId());
                cabinetSlot.setSlotNo(i + 1 + "");
                cabinetSlot.setCreateTime(new Date());
                cabinetSlot.setCreateBy(SecurityUtils.getUsername());
                cabinetSlotMapper.insert(cabinetSlot);
            }

        } else {
            //没有修改柜机类型
            cabinet.setUpdateTime(new Date());
            cabinet.setUpdateBy(SecurityUtils.getUsername());
            this.updateById(cabinet);
        }
        return 1;
    }

    /**
     * 删除柜机
     * @param idList
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int removeCabinet(List<Long> idList) {
        //删除柜机
        this.removeCabinet(idList);
        //删除柜机插槽
        cabinetSlotMapper.delete(new LambdaQueryWrapper<CabinetSlot>().in(
                CabinetSlot::getCabinetId, idList
        ));
        return 1;
    }

    /**
     * 搜索未使用柜机
     * @param keyword 柜机编号，模糊匹配
     * @return
     */
    @Override
    public List<Cabinet> searchNoUseList(String keyword) {
        return this.list(new LambdaQueryWrapper<Cabinet>().like(
                Cabinet::getCabinetNo, keyword)
                .eq(Cabinet::getStatus, "0"));
    }

    /**
     * 获取充电宝柜机全部详细信息
     * @param id
     * @return
     */
    @Override
    public Map<String, Object> getAllInfo(Long id) {
        // 查询柜机信息
        Cabinet cabinet = this.getById(id);

        // 查询插槽信息
        List<CabinetSlot> cabinetSlotList = cabinetSlotMapper.selectList(new LambdaQueryWrapper<CabinetSlot>().eq(CabinetSlot::getCabinetId, cabinet.getId()));
        // 获取可用充电宝id列表
        List<Long> powerBankIdList = cabinetSlotList.stream().filter(item -> null != item.getPowerBankId()).map(CabinetSlot::getPowerBankId).toList();
        if(!CollectionUtils.isEmpty(powerBankIdList)) {
            List<PowerBank> powerBankList = powerBankService.listByIds(powerBankIdList);
            //toMap中的powerBank是lambda表达式，powerBank是参数,所以powerBank的命名首字母要小定，不然sonarLint会报错
            Map<Long,PowerBank> powerBankIdToPowerBankMap = powerBankList.stream()
                    .collect(Collectors.toMap(PowerBank::getId, powerBank -> powerBank));
            cabinetSlotList.forEach(item -> item.setPowerBank(powerBankIdToPowerBankMap.get(item.getPowerBankId())));
        }

        return Map.of("cabinet", cabinet, "cabinetSlotList", cabinetSlotList);
    }
}
